
#include "Tcpserver.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "uitil.hpp"
#include <iostream>
#include <string>
#include <unordered_map>
#include <sstream>

using namespace SocketModule;
using namespace LogModule;
const std::string webroot = "./wwwroot";
const std::string homepage = "index.html";

const std::string gspace = " ";
const std::string glinespace = "\r\n";
const std::string glinesep = ": ";
const std::string page_404 = "/404.html";

// 请求
class HttpRequest
{
public:
    // 序列化，不用写
    std::string Serilaze()
    {
        return std::string();
    }
    void ParseLine(std::string &reqline)
    {
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _version;
    }
    // 反序列化
    void Deserilaze(std::string &reqstr)
    {
        // 1,提取请求行
        std::string reqline;
        bool res = util::ReadOneLine(reqstr, &reqline, glinespace);
        // 对请求行进行反序列化
        ParseLine(reqline);
        if (_uri == "/")
            _uri = webroot + _uri + homepage;
        else
            _uri = webroot + _uri;
    }
    std::string GetUri()
    {
        return _uri;
    }

private:
    // 第一行信息
    std::string _method;
    std::string _uri;
    std::string _version;
    // 请求报头
    std::unordered_map<std::string, std::string> _headers;
    // 空行
    std::string _blankline;
    // 正文
    std::string _text;
};

// 应答
class HttpResponse
{
public:
    HttpResponse()
        : _version("HTTP/1.0"),
          _blankline(glinespace)
    {
    }
    // 序列化
    std::string Serilaze()
    {
        std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace;
        std::string resp_header;
        for (auto &header : _headers)
        {
            std::string line = header.first + glinesep + header.second + glinespace;
            resp_header += line;
        }

        return status_line + resp_header + _blankline + _text;
    }
    // 反序列化，不需要写
    bool Deserilaze(std::string &in)
    {
        return true;
    }
    void Settargetfile(const std::string &target)
    {
        _targetfile = target;
    }
    // 提供一个设置退出码的接口
    void setCode(int code)
    {
        _code = code;
        switch (_code)
        {
        case 200:
            _desc = "Ok";
            break;
        case 404:
            _desc = "Not Found";
            break;
        default:
            break;
        }
    }
    //设置报头
    void setHeader(const std::string& key,const std::string& value)
    {
        auto it=_headers.find(key);
        if(it!=_headers.end())
        return;
        
        _headers.insert(std::make_pair(key,value));
    }

    void MakeResponse()
    {
        bool res = util::ReadFileContent(_targetfile, &_text); // 浏览器请求的资源
        std::string key="Contet-Length";
        int filesize=0;
        if (!res)
        {
            setCode(404);
            // 访问的资源不存在，给用户返回404界面
            _targetfile = webroot + page_404;
            util::ReadFileContent(_targetfile, &_text);
            //设置报头Conent_Length属性
            filesize=util::Filesize(_targetfile);
            //拼上长度后，浏览器访问会出现问题，长度不匹配的问题
        }
        else
        {
            setCode(200);
            filesize=util::Filesize(_targetfile);
        }
        setHeader(key,std::to_string(filesize));
    }
    // void MakeResponse()
    // {
    //     bool res = util::ReadFileContent(_targetfile, &_text); // 浏览器请求的资源
    //     int filesize=0;
    //     if (!res)
    //     {
    //         setCode(404);
    //         // 访问的资源不存在，给用户返回404界面
    //         _targetfile = webroot + page_404;
    //         util::ReadFileContent(_targetfile, &_text);
    //         //设置报头Conent_Length属性
    //         filesize=util::Filesize(_targetfile);
    //         //拼上长度后，浏览器访问会出现问题，长度不匹配的问题
    //         setHeader("Contet-Length",std::to_string(filesize));
    //     }
    //     else
    //     {
    //         setCode(200);
    //         filesize=util::Filesize(_targetfile);
    //         setHeader("Contet-Length",std::to_string(filesize));
    //     }
    // }

public:
    // 第一行信息
    std::string _version;
    int _code;         // 状态码
    std::string _desc; // 状态码对应的错误描述
    // 响应报头
    std::unordered_map<std::string,std::string> _headers;
    // 空行
    std::string _blankline;
    // 正文
    std::string _text;
    // 其他属性
    std::string _targetfile;
};

// HTTP协议
class HTTP
{
public:
    HTTP(uint16_t port)
        : tsvrp(std::make_unique<Tcpserver>(port))
    {
    }
    ~HTTP()
    {
    }
    // 处理请求
    void HandlerHTTPRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        // 收到请求
        std::string httpreq;
        int n = sock->Recv(&httpreq);

        if (n > 0)
        {
            // 反序列化请求
            HttpRequest req;
            req.Deserilaze(httpreq);

            // 构建应答
            HttpResponse resp;
            // 设置目标文件
            resp.Settargetfile(req.GetUri());
            resp.MakeResponse();

            std::string resp_str = resp.Serilaze();
            sock->Send(resp_str);
        }
        //  收到请求
        //  std::string httpreqstr;
        //  假设：概率大，读到了完整的请求
        //  sock->Recv(&httpreqstr); // 浏览器给我发过来的是一个大的http字符串, 其实我们的recv也是有问题的。tcp是面向字节流的.
        //  std::cout << httpreqstr;

        //  直接构建http应答. 内存级别+固定
        //  HttpResponse resp;
        //  resp._version = "HTTP/1.1";
        //  resp._code = 200; // success
        //  resp._desc = "OK";

        //  std::string filename = webroot + homepage; // "./wwwroot/index.html";
        //  bool res = util::ReadFileContent(filename, &(resp._text));
        //  (void)res;
        //  std::string response_str = resp.Serilaze();
        //  sock->Send(response_str);
    }
    void start()
    {
        tsvrp->start([this](std::shared_ptr<Socket> &sock, InetAddr &client)
                     { this->HandlerHTTPRequest(sock, client); });
    }

private:
    std::unique_ptr<Tcpserver> tsvrp;
};
